package heap

import "lesson01/classfile"

type InterfaceMethodRef struct {
	MemberRef
	method *Method
}

func newInterfaceMethodRef(cp *ConstantPool, method *classfile.ConstantInterfaceMethodrefInfo) *InterfaceMethodRef {
	methodRef := &InterfaceMethodRef{}
	methodRef.cp = cp
	methodRef.copyMemberRefInfo(&method.ConstantMemberrefInfo)
	return methodRef
}

func (e *InterfaceMethodRef) ResolveInterfaceMethod() *Method {
	if e.method == nil {
		e.resolveInterfaceMethodRef()
	}
	return e.method
}

// resolveInterfaceMethodRef jvms8 5.4.3.4
func (e *InterfaceMethodRef) resolveInterfaceMethodRef() {
	class := e.cp.class
	resolvedClass := e.ResolvedClass()
	if !resolvedClass.IsInterface() {
		panic("java.lang.IncompatibleClassChangeError")
	}

	method := lookupInterfaceMethod(resolvedClass, e.name, e.descriptor)
	if method == nil {
		panic("java.lang.NoSuchMethodError")
	}
	if !method.isAccessibleTo(class) {
		panic("java.lang.IllegalAccessError")
	}
	e.method = method
}

func lookupInterfaceMethod(clazz *Class, name, descriptor string) *Method {
	for _, method := range clazz.methods {
		if method.name == name && method.descriptor == descriptor {
			return method
		}
	}

	return lookupMethodInInterfaces(clazz.interfaces, name, descriptor)
}
